<?php

namespace App\Http\Controllers\Api;

use App\Constant;
use App\Exceptions\ApiException;
use App\Http\Controllers\Controller;
use App\Models\FrontendUser;
use App\Models\LotteryRecord;
use App\Models\Product;
use Illuminate\Contracts\Cache\LockTimeoutException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;

class ActivityController extends Controller
{
    /** 查询用户邀请排名 */
    public function listInviteRankings($activityId)
    {
        $topInvitors = $this->authUserQuery()
            ->select(['parent_id', \DB::raw('count(*) as count')])
            ->groupBy('parent_id')
            ->orderByDesc('count')
            ->limit(50)
            ->get();

        $users = FrontendUser::query()
            ->whereIn('id', Arr::pluck($topInvitors, 'parent_id'))
            ->get()
            ->mapWithKeys(function (FrontendUser $user) {
                return [$user->id => $user];
            });

        $myRanking = [];
        $rankings = [];
        /** @var FrontendUser $me */
        $me = Auth::guard(Constant::GUARD_API)->user();
        if ($me) {
            $myRanking = [
                'ranking' => '-',
                'invite_count' => $this->authUserQuery()->where('parent_id', $me->id)->count(),
            ];
        }
        $ranking = 1;
        /** @var FrontendUser $invitor */
        foreach ($topInvitors as $invitor) {
            /** @var FrontendUser $user */
            $user = Arr::get($users, $invitor->parent_id);
            if ($me && $me->id === $user->id) {
                $myRanking['ranking'] = $ranking;
            }
            $rankings[] = [
                'ranking' => $ranking++,
                'mobile' => hide_mobile($user->mobile),
                'invite_count' => $invitor->count,
            ];
        }

        return [
            'rankings' => $rankings,
            'my_ranking' => $myRanking,
        ];
    }

    /** 查询奖品列表和剩余抽奖次数 */
    public function lotteryInfo($id)
    {
        $activityConfigs = $this->getActivityConfig();
        $awardsConfig = Arr::get($activityConfigs, 'awards', []);
        $productIds = array_keys($awardsConfig);
        $products = Product::query()
            ->whereIn('id', $productIds)
            ->get()
            ->mapWithKeys(function (Product $product) {
                return [$product->id => $product];
            });
        $awards = [];
        //查询商品的中奖次数
        $productUsed = LotteryRecord::query()
            ->where('activity_id', $id)
            ->select(['product_id', \DB::raw('count(*) as count')])
            ->groupBy('product_id')
            ->get()
            ->mapWithKeys(function (LotteryRecord $record) {
                return [$record->product_id => $record->count];
            });
        foreach ($awardsConfig as $productId => $issueCount) {
            /** @var Product $product */
            $product = Arr::get($products, $productId);
            $usedCount = Arr::get($productUsed, $productId, 0);
            $awards[] = [
                'key' => $product->id,
                'name' => $product->name,
                'cover_image_url' => $product->logo_url,
                'issue_count' => $issueCount,
                'left_count' => max($issueCount - $usedCount, 0),
            ];
        }
        /** @var FrontendUser $user */
        $user = auth()->user();
        //查询用户邀请数量
        $inviteCount = $this->authUserQuery()->where('parent_id', $user->id)->count();
        //查询用户已抽奖次数
        $drawCount = LotteryRecord::query()->where('activity_id', $id)->where('user_id', $user->id)->count();
        $maxDrawCount = Arr::get($activityConfigs, 'max_draw_count', 1);
        //返回可抽奖次数
        return [
            'awards' => $awards,
            'draw_times' => $drawCount,
            'left_times' => min(floor($inviteCount / 2), $maxDrawCount) - $drawCount,
            'max_times' => $maxDrawCount,
        ];
    }

    /** 抽奖 */
    public function draw($id)
    {
        $lock = \Cache::lock('activity_lottery_draw' . $id, 30);

        try {
            $lock->block(1); // 如果获取不到锁，则等待1秒
            $activityConfigs = $this->getActivityConfig();
            //查询用户可抽奖次数
            /** @var FrontendUser $user */
            $user = auth()->user();
            //查询用户邀请数量
            $inviteCount = $this->authUserQuery()->where('parent_id', $user->id)->count();
            //查询用户已抽奖次数
            $drawCount = LotteryRecord::query()->where('activity_id', $id)->where('user_id', $user->id)->count();
            $maxDrawCount = Arr::get($activityConfigs, 'max_draw_count', 1);
            $canDrawCount = max(0, floor($inviteCount / 2) - $drawCount);
            if ($drawCount >= $maxDrawCount) {
                throw new ApiException('超出抽奖次数限制');
            }
            if ($canDrawCount <= 0) {
                throw new ApiException('您的抽奖次数不足');
            }
            //查询可用奖品
            $awardsConfig = Arr::get($activityConfigs, 'awards', []);
            //查询商品的中奖次数
            $productUsed = LotteryRecord::query()
                ->where('activity_id', $id)
                ->select(['product_id', \DB::raw('count(*) as count')])
                ->groupBy('product_id')
                ->get()
                ->mapWithKeys(function (LotteryRecord $record) {
                    return [$record->product_id => $record->count];
                });
            $candidate = [];
            foreach ($awardsConfig as $productId => $issueCount) {
                $usedCount = Arr::get($productUsed, $productId, 0);
                if ($issueCount > $usedCount) {
                    $candidate[] = $productId;
                }
            }
            if (empty($candidate)) {
                throw new ApiException('奖品已发完');
            }
            //随机选中一个
            $award = Product::query()->whereIn('id', $candidate)->inRandomOrder()->first();
            $record = new LotteryRecord();
            $record->activity_id = $id;
            $record->user_id = $user->id;
            $record->product_id = $award->id;
            $record->save();
            //返回中奖奖品及剩余抽奖次数
            return [
                'award' => [
                    'key' => $award->id,
                    'name' => $award->name,
                    'cover_image_url' => $award->logo_url,
                ],
                'left_times' => $canDrawCount - 1,
            ];
        } catch (LockTimeoutException $e) {
            throw new ApiException('抽奖人数过多，请稍后再试');
        } finally {
            $lock->release();
        }
    }

    private function authUserQuery()
    {
        $activityConfig = $this->getActivityConfig();
        $startDate = Arr::get($activityConfig, 'start');
        $endDate = Arr::get($activityConfig, 'end');

        return FrontendUser::query()
            ->join('user_auths', 'frontend_users.id', 'user_auths.user_id')
            ->where('agent_id', request()->agent_id)
            ->whereDate('frontend_users.created_at', '>=', $startDate)
            ->whereDate('frontend_users.created_at', '<=', $endDate)
            ->where('parent_id', '>', 0);
    }

    private function getActivityConfig()
    {
        $activityConfigJson = config('services.activity_config');
        if (!$activityConfigJson) {
            throw new ApiException('活动未配置');
        }

        return json_decode($activityConfigJson, true);
    }
}
